At Gunpoint
Category: Reversing
Points: 200
Author: freddy
Description:
You’re the sheriff of a small town, investigating news about a gangster squad passing by. Rumor has it they’re easy to outsmart, so you have just followed one to their encampment by the river. You know you can easily take them out one by one, if you would just know their secret handshake..
Download: gunpoint_2daf5fe3fb236b398ff9e5705a058a7f.dat
Write-up
$file gunpoint_2daf5fe3fb236b398ff9e5705a058a7f.dat
gunpoint_2daf5fe3fb236b398ff9e5705a058a7f.dat: Gameboy ROM: "FLUX", [ROM ONLY], ROM: 256Kbit
Nice, a gameboy ROM. Searching for gameboy emulator
gets us Visual Boy Advance as the first result. We need to change the extension to gbc
to be able to open the file in the emulator. After running the game for some time or doing options->emulator->speed up toggle
, we get:
So probably we need to guess the secret key combination. Fortunately emulator has also dissasembler and IDA is also able to dissaseble the code. Here is some thorough description of Gameboy hardware. The most interesting part is here:
FF00
Name - P1
Contents - Register for reading joy pad info
and determining system type. (R/W)
Bit 7 - Not used
Bit 6 - Not used
Bit 5 - P15 out port
Bit 4 - P14 out port
Bit 3 - P13 in port
Bit 2 - P12 in port
Bit 1 - P11 in port
Bit 0 - P10 in port
This is the matrix layout for register $FF00:
P14 P15
| |
P10-------O-Right----O-A
| |
P11-------O-Left-----O-B
| |
P12-------O-Up-------O-Select
| |
P13-------O-Down-----O-Start
| |
Example code:
Game: Ms. Pacman
Address: $3b1
LD A,$20 <- bit 5 = $20
LD ($FF00),A <- select P14 by setting it low
LD A,($FF00)
LD A,($FF00) <- wait a few cycles
CPL <- complement A
AND $0F <- get only first 4 bits
SWAP A <- swap it
LD B,A <- store A in B
LD A,$10
LD ($FF00),A <- select P15 by setting it low
LD A,($FF00)
LD A,($FF00)
LD A,($FF00)
LD A,($FF00)
LD A,($FF00)
LD A,($FF00) <- Wait a few MORE cycles
CPL <- complement (invert)
AND $0F <- get first 4 bits
OR B <- put A and B together
LD B,A <- store A in D
LD A,($FF8B) <- read old joy data from ram
XOR B <- toggle w/current button bit
AND B <- get current button bit back
LD ($FF8C),A <- save in new Joydata storage
LD A,B <- put original value in A
LD ($FF8B),A <- store it as old joy data
LD A,$30 <- deselect P14 and P15
LD ($FF00),A <- RESET Joypad
RET <- Return from Subroutine
The button values using the above method are such:
$80 - Start $8 - Down
$40 - Select $4 - Up
$20 - B $2 - Left
$10 - A $1 - Right
Let's say we held down A, Start, and Up.
The value returned in accumulator A would be $94
If we go to Tools->Dissasemble
then we have a fairly good chance we land up in the code that is almost the same. (If not press Next
few times) We can see that the result of the key presses are stored in addresses C0A1
and C0A2
. Counter at address C0A0
is increased each time we press the correct key. Using Tools->Memory viewer
we can see when we press the correct key. The sequence is up, left, down, right, up, left, down, right, B, B A, A
.
Flag is tkCXDJheQDNRN
###Other write-ups and resources